﻿#region Header
// ------------------------ Licence / Copyright ------------------------
// 
// ScrumTable for Scrum Meeting Support
// Copyright © HSR - Hochschule für Technik Rapperswil
// All Rights Reserved
// 
// Author:
//  Michael Gfeller Silvan Gehrig Patrick Boos
// 
// ---------------------------------------------------------------------
#endregion

#region Usings
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Windows.Input;
using ScrumTable.BL.DM.DataManagement;
using ScrumTable.Config.UserManagement;
using ScrumTable.Common.Collections;
using ScrumTable.DL.Data.Common;
using ScrumTable.DL.Data.Common.Config.Driver;
using ScrumTable.UI.ViewModel.Controller;
using Microsoft.Practices.Unity;
using ScrumTable.UI.ViewModel.Data;

#endregion

namespace ScrumTable.UI.ViewModel.View
{
    /// <summary>
    /// Description of the class
    /// </summary>
    public class RegisterViewModel : ViewModelBase
    {
 
        #region Declarations
        //--------------------------------------------------------------------
        // Declarations
        //--------------------------------------------------------------------
        private RelayCommand _goToOk;
        private string _error;
        private int _selectedUser;
        private ObservableCollection<Single<string>> _users;
        private RelayCommand _removeUserCommand;
        private bool _isInChangeMode = true;
        private const string DefaultServerName = "http://localhost";
        private const string LocalHostServerName = "localhost";

        #endregion

        #region Properties
        //--------------------------------------------------------------------
        // Properties
        //--------------------------------------------------------------------  
        /// <summary>
        /// Gets or sets the account manager.
        /// </summary>
        /// <value>The account manager.</value>
        [Dependency] 
        public LoginAccountManager AccountManager { get; set;}

        /// <summary>
        /// Gets or sets the scrum data.
        /// </summary>
        /// <value>The scrum data.</value>
        [Dependency]
        public ScrumViewModelData ScrumData { get; set; }

        public bool InWizardMode
        {
            get { return NaviController.CurrentTarget.IsWizardTarget(); }
        }

        /// <summary>
        /// A list of users
        /// </summary>
        public ObservableCollection<Single<string>> Users 
        {
            get
            {
                if (_users == null)
                {
                    if (AccountManager.CurrentLoginAccount.CryptedLogins.Count > 0)
                    {
                        var names = from x in AccountManager.CurrentLoginAccount.CryptedLogins select new Single<string>(x.Left);
                        _users = new ObservableCollection<Single<string>>(names);
                    }
                    else
                    {
                        var names = from x in AccountManager.CurrentLoginAccount.DeCryptedLogins select new Single<string>(x.Left);
                        _users = new ObservableCollection<Single<string>>(names);
                    }
                    if(_users.Count ==0)
                    {
                        _users.Add(new Single<string>(""));
                        IsInChangeMode = false;
                    }
                }
                return _users;
            }
        }

        /// <summary>
        /// if true, the user changes it settings
        /// </summary>
        public bool IsInChangeMode
        {
            get { return Users.Count > 0 && _isInChangeMode; }
            private set { _isInChangeMode = value; }
        }

        /// <summary>
        /// Copy of the listname
        /// </summary>
        public List<string> ServerList
        {
            get { return new List<string>(AccountManager.ServerList);}
        }
        /// <summary>
        /// Selected index in the Userlist
        /// </summary>
        public int SelectedUserIndex
        {
            get { return _selectedUser; }
            set
            {
                _selectedUser = value;
                SendPropertyChanged("SelectedUserIndex");
            }
        }

        /// <summary>
        /// Gets all projects.
        /// </summary>
        /// <value>The projects.</value>
        public DomainCollection<Project> Projects
        {
            get { return (ScrumData.DataContext != null) ? ScrumData.DataContext.Projects : null; }
        }
        /// <summary>
        /// Gets or sets the error info.
        /// </summary>
        /// <value>connection error info.</value>
        public string ErrorConnect
        {
            get
            {
                return _error;
            }
            set
            {
                _error = value;
                SendPropertyChanged("ErrorConnect");
            }
        }

        /// <summary>
        /// Gets the Command for go forward in the register process. 
        /// </summary>
        /// <value>Command for go forward in the process</value>
        public ICommand GoToOK
        {
            get
            {
                if (_goToOk == null)
                {
                    _goToOk = new RelayCommand(
                        param => GoTo(NavigationTarget.ProjectConfig, param.ToString() ),
                        param => true
                        );
                }
                return _goToOk;
            }
        }

        /// <summary>
        /// Command for Testing the connection
        /// </summary>
        /// <value>Command for connection testing</value>
        public ICommand Connect
        {
            get
            {
                var test  = new RelayCommand(
                        param => TestConnect( param.ToString()),
                        param => true
                        );
                return test;
            }
        }

        /// <summary>
        /// Command for removing a user from the list
        /// </summary>
        /// <value>command</value>
        public ICommand RemoveUser
        {
            get
            {
                if (_removeUserCommand == null)
                {
                    _removeUserCommand = new RelayCommand(
                        param => Users.Remove(param as Single<string>),
                        param => (param != null && Users.Count > 1)
                        );
                }
                return _removeUserCommand;
            }
        }

        public Predicate<string> CheckServerName
        {
            get
            {
                return obj => Uri.IsWellFormedUriString(obj, UriKind.RelativeOrAbsolute);
            }
        }

        public string DataType
        {
            get
            {
                if(string.IsNullOrEmpty(AccountManager.CurrentLoginAccount.DataType ))
                {
                    DataType =  "ScrumTable - Local XML data storage assembly.";
                }
                return AccountManager.CurrentLoginAccount.DataType;
            }
            set
            {
                
                SchemaName = null;
                ScrumData.CurrentProject = null;
                ScrumData.Disconnect(false);
                SendPropertyChanged("Projects");
                AccountManager.CurrentLoginAccount.DataType = value;
                SendPropertyChanged("DataType");
                SendPropertyChanged("IsLoginRequired");
                SendPropertyChanged("IsPathToSourceRequired");
                SendPropertyChanged("DataLinkType");
                
                if (value != null)
                {
                    var assembly = ScrumViewModelData.GetDataAssembly(value);
                    var schema = assembly.DataSchemaSelector.FirstOrDefault();
                    if (schema != null)
                    {
                        SchemaName = schema.Name;
                    }
                }
                NaviController.GoTo(NavigationTarget.RegisterView);
            }
        }

        public string SchemaName
        {
            get { return AccountManager.CurrentLoginAccount.SchemaName; }
            set
            {
                ScrumData.CurrentProject = null;
                ScrumData.Disconnect(false);
                SendPropertyChanged("Projects");

                AccountManager.CurrentLoginAccount.SchemaName = value;
                SendPropertyChanged("SchemaName");
                NaviController.GoTo(NavigationTarget.RegisterView);
            }
        }

        public bool IsLoginRequired
        {
            get
            {
                if(DataType == null)
                {
                    return true;
                }
                var assembly = ScrumViewModelData.GetDataAssembly(DataType);
                if(assembly!=null)
                {
                    return assembly.AssemblyRequiresStrongAuthentication;
                }
                return true;
            }
        }

        public bool IsPathToSourceRequired
        {
            get { return DataLinkType != DataSourceLinkFormat.None; }
        }

        public DataSourceLinkFormat DataLinkType
        {
            get
            {
                if (DataType == null)
                {
                    return DataSourceLinkFormat.None;
                }
                var assembly = ScrumViewModelData.GetDataAssembly(DataType);
                if (assembly != null)
                {
                    return assembly.AssemblyRequiredLinkFormat;
                }
                return DataSourceLinkFormat.None;
            }
        }

        public IDriverConfigSource DriverConfig
        {  
            get
            {
                 var assembly = ScrumViewModelData.GetDataAssembly(DataType);
                 if (assembly != null)
                 {
                     string configName = AccountManager.CurrentLoginAccount.GetConfigForConnection(DataType);
                     if (!string.IsNullOrEmpty(configName))
                     {
                         var config = assembly.DriverConfigSelector.FirstOrDefault(x => x.Name == configName);
                         //config not found -> reset to default
                         if(config == null)
                         {
                             config = assembly.DriverConfigSelector.Default;
                             AccountManager.CurrentLoginAccount.SetConfigForConnection(DataType, assembly.DriverConfigSelector.Default.Name);

                         }
                         return config;
                     }
                 }
                return null;
            }
        }
 
        #endregion

        #region Constructors / Destructor
        //--------------------------------------------------------------------
        // Constructors / Destructor
        //--------------------------------------------------------------------

        public RegisterViewModel()
        {
            ScrumDataGlobal.PropertyChanged += OnScrumDataGlobalPropertyChanged;
        }

       

        #endregion

        #region Methods
        //--------------------------------------------------------------------
        // Methods
        //--------------------------------------------------------------------

        protected override void ReleaseManagedResources()
        {
            ScrumDataGlobal.PropertyChanged -= OnScrumDataGlobalPropertyChanged;
            base.ReleaseManagedResources();
            
        }
        public void AddServer(string name)
        {
            if (!string.IsNullOrEmpty(name))
            {
                if (!AccountManager.ServerList.Contains(name))
                {
                    AccountManager.ServerList.Add(name);
                }
                SendPropertyChanged("ServerList");
            }
        }

        public void ActivateAdvancedSettings()
        {
            if (string.IsNullOrEmpty(AccountManager.CurrentLoginAccount.GetConfigForConnection(DataType)))
            {
                var assembly = ScrumViewModelData.GetDataAssembly(DataType);
                if (assembly != null)
                {
                    var config = assembly.DriverConfigSelector.Create();
                    AccountManager.CurrentLoginAccount.SetConfigForConnection(DataType, config.Name);
                }
            }
            SendPropertyChanged("DriverConfig");
        }


        public void RemoveServer(string name)
        {
            if (!string.IsNullOrEmpty(name) && AccountManager.ServerList.Contains(name))
            {
                AccountManager.ServerList.Remove(name);
                SendPropertyChanged("ServerList");
            }
        }
 


        private void TestConnect( string pin)
        {
            pin = (string.IsNullOrEmpty(pin) || pin.Length<4) ? "1234" : pin;
            ErrorConnect = "";
            SetLoginAccNotRequired();
            AccountManager.CurrentLoginAccount.Pin = pin;
            ScrumData.Connect(pin, NavigationTarget.Null ,e =>  ErrorConnect = e );
            NaviController.GoTo(NavigationTarget.RegisterView);
        } 
     

        private void GoTo(NavigationTarget toGo, string pin)
        {
            pin = (IsLoginRequired) ? pin : "1234";
            ErrorConnect = "";
            SetLoginAccNotRequired();
            AccountManager.CurrentLoginAccount.Pin = pin;
            ScrumData.Connect(pin, NavigationTarget.ProjectConfig, true,  e=>ErrorConnect=e);
            if (DriverConfig != null && DriverConfig.CanSave)
            {
                DriverConfig.Save();
            }
            AccountManager.SaveLogin();
        }

        private void SetLoginAccNotRequired()
        {
            if (!IsLoginRequired)
            {
                if (ServerList.Count == 0)
                {
                    ServerList.Add(DefaultServerName);
                }

                AccountManager.CurrentLoginAccount.ServerName = string.IsNullOrEmpty(AccountManager.CurrentLoginAccount.ServerName)
                                                                        ? LocalHostServerName
                                                                        : AccountManager.CurrentLoginAccount.ServerName; 
                AccountManager.CurrentLoginAccount.SetLogin("Demo", "1234");
            }
        }

        private bool CanDeleteUser(object param)
        {
            return (param != null && Users.Count > 1);
        }
        #endregion

        #region Events
        //--------------------------------------------------------------------
        // Events
        //--------------------------------------------------------------------


        void OnScrumDataGlobalPropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
        {
            if (e.PropertyName == "DataContext")
            {
                SendPropertyChanged("Projects");
            }

        }

        #endregion
    }
}